/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * All rights reserved.                                                   *
 *                                                                        *
 * Primary Authors:                                                       *
 *   Artur Szostak <artursz@iafrica.com>                                  *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/// \ingroup macros
/// \file ExtractDDLs.C
/// \brief Macro for extracting DDL raw data from different AliRawReaders.
///
/// \author Artur Szostak <artursz@iafrica.com>
///
/// This macro is used to extract DDL raw data files for the muon spectrometer
/// from different data sources using an AliRawReader. This macro will generate
/// directories in the form rawX where X is an integer. This is the typical
/// directory layout generated by AliRoot simulations.
///

#if !defined(__CINT__) || defined(__MAKECINT__)
#include "TSystem.h"
#include "TString.h"
#include "AliRawReader.h"
#include "AliRawDataHeader.h"
#include "Riostream.h"
#include <fstream>
using std::fstream;
#else
#error This macro must be compiled.
#endif

/**
 * Writes all DDL files for the current event from the AliRawReader.
 */
void WriteDDLs(AliRawReader* rawReader, const TString& dir, const char* detector)
{
	while (rawReader->ReadHeader())
	{
		// Allocate memory for the DDL.
		UInt_t bufferSize = rawReader->GetDataSize() + sizeof(AliRawDataHeader);
		UChar_t* buffer = new UChar_t[bufferSize];
		if (buffer == NULL)
		{
			cerr << "ERROR: Out of memory!" << endl;
			continue;
		}
		
		// Copy the CDH header.
		memcpy(buffer, rawReader->GetDataHeader(), sizeof(AliRawDataHeader));
		
		UChar_t* payload = buffer + sizeof(AliRawDataHeader);
		UInt_t payloadSize = bufferSize - sizeof(AliRawDataHeader);
		
		// Now copy the DDL payload.
		if (! rawReader->ReadNext(payload, payloadSize))
		{
			cerr << "ERROR: Failed to read from AliRawReader." << endl;
			delete [] buffer;
			continue;
		}
		
		// Write the file.
		TString filename = dir;
		filename += "/";
		filename += detector;
		filename += "_";
		char num[32];
		sprintf(num, "%d", rawReader->GetEquipmentId());
		filename += num;
		filename += ".ddl";
		
		fstream file(filename.Data(), fstream::out | fstream::binary);
		if (! file)
		{
			cerr << "ERROR: Could not create file: " << filename.Data() << endl;
			delete [] buffer;
			continue;
		}
		file.write((char*)buffer, bufferSize);
		if (! file)
		{
			cerr << "ERROR: Failed to write to file: " << filename.Data() << endl;
			file.close();
			delete [] buffer;
			continue;
		}
		file.close();
		
		delete [] buffer;
	}
}

/**
 * Extracts muon spectrometer raw DDL data files from a data source.
 * \param dataSource  This is the raw data to use. It can either be a directory name
 *      containing rawX directories with raw DDL files, a .root file containing raw
 *      data or a DATE raw data file.
 * \param firstEvent The first event number to extract.
 * \param lastEvent The last event number to extract. If set to a negative number then
 *      all events from <i>firstEvent</i> to the end of the data stream is extracted.
 * \param outputDir  This is the output directory to write the raw data to. The default
 *      is to use the current directory.
 */
void ExtractDDLs(
		const char* dataSource = "raw.root",
		Int_t firstEvent = 0, Int_t lastEvent = -1,
		const char* outputDir = "."
	)
{
	AliRawReader* rawReader = AliRawReader::Create(dataSource);
	if (rawReader == NULL)
	{
		cerr << "ERROR: Could not create AliRawReader." << endl;
		return;
	}
	
	Int_t count = 0;
	if (lastEvent < 0) lastEvent = rawReader->GetNumberOfEvents() - 1;
	Int_t event = firstEvent;
	rawReader->GotoEvent(firstEvent);
	while (event <= lastEvent)
	{
		char num[32];
		sprintf(num, "%d", count);
		TString dir = outputDir;
		dir += "/raw";
		dir += num;
		if (gSystem->MakeDirectory(dir.Data()) != 0)
		{
			cerr << "ERROR: Could not create directory: " << dir.Data() << endl;
		}
		else
		{
			rawReader->Select("MUONTRK", 0, 19);
			WriteDDLs(rawReader, dir, "MUONTRK");
			rawReader->Select("MUONTRG", 0, 1);
			WriteDDLs(rawReader, dir, "MUONTRG");
		}
		++count;
		++event;
		rawReader->NextEvent();
	}

	delete rawReader;
}

